﻿using Microsoft.Extensions.Logging;
using Quartz;
using Quartz.Impl;
using Quartz.Spi;
using System.Collections.Specialized;
using TaskMasterByQuartz.Domain.Enums;
using TaskMasterByQuartz.Domain.Helper;
using TaskMasterByQuartz.Domain.InterfaceRepository;
using TaskMasterByQuartz.Domain.ServiceRepository;


namespace TaskMasterByQuartz.Infrastructure.Implementations
{
    /// <summary>
    /// 调度中心 [单例]
    /// </summary>
    public class SchedulerCenter : ISchedulerCenter
    {
        /// <summary>
        /// 调度器
        /// </summary>
        private IScheduler scheduler;
        private readonly ILogger<SchedulerCenter> logger;
        private readonly CreateTriggerHelper createTriggerHelper;
        private readonly ISchedulerFactory schedulerFactory;
        private readonly IJobFactory jobFactory;

        public SchedulerCenter(ILogger<SchedulerCenter> logger, CreateTriggerHelper createTriggerHelper, ISchedulerFactory schedulerFactory, IJobFactory jobFactory)
        {
            this.logger = logger;
            this.createTriggerHelper = createTriggerHelper;
            scheduler = schedulerFactory.GetScheduler().GetAwaiter().GetResult();
            this.schedulerFactory = schedulerFactory;
            this.jobFactory = jobFactory;
            scheduler.JobFactory = jobFactory;
        }

        /// <summary>
        /// 检查任务是否存在
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<bool> CheckScheduleJobAsync(string jobGroupName,string jobName)
        {
            var jobKey = new JobKey(jobName, jobGroupName);
            return await scheduler.CheckExists(jobKey);
        }

        /// <summary>
        /// 添加一个工作调度
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="runNumber"></param>
        /// <returns></returns>
        public async Task AddScheduleJobAsync(
            string jobGroupName,
            string jobName,
            DateTimeOffset? endTime,
            JobTypeEnum jobType,
            string? requestUrl,
            string? headers,
            string? requestParameters,
            RequestTypeEnum? requestType,
            TriggerTypeEnum triggerType,
             string cron, DateTimeOffset beginTime, int? runTimes, int IntervalSecond,string description,
            long? runNumber = null
            )
        {
            //http请求配置
            var httpDir = new Dictionary<string, string>()
                {
                    { Constant.EndAt, endTime.ToString()},
                    { Constant.JobTypeEnum, ((int)jobType).ToString()},
                };
            if (runNumber.HasValue)
                httpDir.Add(Constant.RUNNUMBER, runNumber.ToString());

            IJobConfigurator jobConfigurator = null;
            if (jobType == JobTypeEnum.Url)
            {
                jobConfigurator = JobBuilder.Create<MyHttpJob>();
                httpDir.Add(Constant.REQUESTURL, requestUrl);
                httpDir.Add(Constant.HEADERS, headers);
                httpDir.Add(Constant.REQUESTPARAMETERS, requestParameters);
                httpDir.Add(Constant.REQUESTTYPE, requestType.ToString());
            }

            // 定义这个工作，并将其绑定到我们的IJob实现类                
            IJobDetail job = jobConfigurator
                .SetJobData(new JobDataMap(httpDir))
                .WithDescription(description)
                .WithIdentity(jobName, jobGroupName)
                .Build();

            // 创建触发器
            ITrigger trigger;
            //校验是否正确的执行周期表达式
            if (triggerType == TriggerTypeEnum.Cron)//CronExpression.IsValidExpression(entity.Cron))
            {
                trigger = createTriggerHelper.CreateCronTrigger(jobName,jobGroupName,cron,beginTime);
            }
            else
            {
                trigger = createTriggerHelper.CreateSimpleTrigger(jobName, jobGroupName, cron, beginTime,runTimes,IntervalSecond);
            }


            // 告诉Quartz使用我们的触发器来安排作业
            await scheduler.ScheduleJob(job, trigger);
            //scheduler1.Start();
        }
        /// <summary>
        /// 暂停指定的计划
        /// </summary>
        /// <param name="jobGroup">任务分组</param>
        /// <param name="jobName">任务名称</param>
        /// <returns></returns>
        public async Task StopScheduleJobAsync(string jobGroup, string jobName)
        {
            await scheduler.PauseJob(new JobKey(jobName, jobGroup));
        }

        /// <summary>
        /// 删除指定的计划
        /// </summary>
        /// <param name="jobGroup">任务分组</param>
        /// <param name="jobName">任务名称</param>
        /// <returns></returns>
        public async Task DelScheduleJobAsync(string jobGroup, string jobName)
        {
            await scheduler.DeleteJob(new JobKey(jobName, jobGroup));
        }

        /// <summary>
        /// 恢复运行暂停的任务
        /// </summary>
        /// <param name="jobName">任务名称</param>
        /// <param name="jobGroup">任务分组</param>
        public async Task ResumeJobAsync(string jobGroup, string jobName)
        {
            await scheduler.ResumeJob(new JobKey(jobName, jobGroup));
        }

        /// <summary>
        /// 获取指定 标识的作业（Job）的详细信息
        /// </summary>
        /// <param name="jobName">任务名称</param>
        /// <param name="jobGroup">任务分组</param>
        /// <returns></returns>
        public async Task<IJobDetail> QueryJobDetailAsync(string jobGroup, string jobName)
        {
            return await scheduler.GetJobDetail(new JobKey(jobName, jobGroup));
        }

        /// <summary>
        /// 获取指定作业（Job）关联的所有触发器（Triggers）
        /// </summary>
        /// <param name="jobName">任务名称</param>
        /// <param name="jobGroup">任务分组</param>
        /// <returns>包含所有触发器的列表</returns>
        public async Task<IReadOnlyCollection<ITrigger>> QueryTriggersOfJobAsync(string jobGroup, string jobName)
        {
            return await scheduler.GetTriggersOfJob(new JobKey(jobName, jobGroup));
        }

        /// <summary>
        /// 立即执行
        /// </summary>
        /// <param name="jobKey"></param>
        /// <returns></returns>
        public async Task<bool> TriggerJobAsync(JobKey jobKey)
        {
            await scheduler.TriggerJob(jobKey);
            return true;
        }

        /// <summary>
        /// 获取job日志
        /// </summary>
        /// <param name="jobKey"></param>
        /// <returns></returns>
        public async Task<List<string>> GetJobLogsAsync(JobKey jobKey)
        {
            var jobDetail = await scheduler.GetJobDetail(jobKey);
            return jobDetail.JobDataMap[Constant.LOGLIST] as List<string>;
        }

        /// <summary>
        /// 获取运行次数
        /// </summary>
        /// <param name="jobKey"></param>
        /// <returns></returns>
        public async Task<long> GetRunNumberAsync(JobKey jobKey)
        {
            var jobDetail = await scheduler.GetJobDetail(jobKey);
            return jobDetail.JobDataMap.GetLong(Constant.RUNNUMBER);
        }
    }
}

